﻿//Szu
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;

namespace CharacterLibrary
{
    public class Ghost:Character
    {
        public static string PATH = @"CINEMA4D/ghost";
        public bool canMove { get; set; }
        private bool firstSet = true;

        public Ghost(ContentManager content, GraphicsDeviceManager graphics, int x, int z, float speed)
            : base(graphics,x,z)
        {
            this.speed = speed;
            Vector3 position = new Vector3(x, Global.ConstantVision.InitYObjectPosition, z);
            model = content.Load<Model>(PATH);
            this.position = position;
            bornPlace = position;
        }

        public Ghost(ContentManager content, GraphicsDeviceManager graphics, int x, int z, Random random, float min, float max)
            : base(graphics, x, z)
        {
            this.speed = (float)(random.NextDouble() * (max - min) + min);
            Vector3 position = new Vector3(x, Global.ConstantVision.InitYObjectPosition, z);
            model = content.Load<Model>(PATH);
            this.position = position;
            bornPlace = position;
        }

        public void randomSpeed(Random random, float min, float max){
            base.speed = (float)(random.NextDouble()*(max-min) + min);
        }
        public override void Draw()
        {
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.World = Matrix.CreateScale(1.0f, Global.ConstantVision.GhostYScale, 1.0f) * Matrix.CreateRotationY(((float)Math.PI) * (int)direction / 2 + (float)(Math.PI)) * Matrix.CreateTranslation(position);
                    effect.View = Global.Vision.view;
                    effect.Projection = Global.Vision.projection;
                    effect.EnableDefaultLighting();
                }
                mesh.Draw();
            }
        }
        /// <summary>
        /// Wybieranie nowego kierunku.
        /// </summary>
        /// <param name="random">obiekt random</param>
        /// <param name="rows">współrzędne x</param>
        /// <param name="cols">współrzędne y</param>
        /// <param name="reservedPlace">tablica zajętych pól na tablicy</param>
        public void setDirection(Random random, int rows, int cols, bool[,] reservedPlace)
        {
            

            //Wkrycie dotarcia, gdzie możliwa jest zmiana kierunku:
            if (( Math.Abs(this.Pos.X - ((int)this.Pos.X)) < (float)speed / 60) &&
                     ( Math.Abs(this.Pos.Z - ((int)this.Pos.Z)) < (float)speed / 60))
            {
                int posX, posZ;
                int counter = 0, newDirection = random.Next(0, 4);

                posX = (int)Math.Round(this.Pos.X);
                posZ = (int)Math.Round(this.Pos.Z);

                //Wykrycie wychodzenia poza obszar tablicy i automatyczna zmiana kierunku na przeciwny:
                if ( posZ >= cols - 1){
                    this.Direction = (DirectionType)2;
                    canMove = true;
                    return;
                }
                if ( posX >= rows - 1)
                {
                    this.Direction = (DirectionType)3;
                    canMove = true;
                    return; 
                }
                if ( posZ < 1)
                {
                    this.Direction = (DirectionType)0;
                    canMove = true;
                    return;
                }
                if ( posX < 1)
                {
                    this.Direction = (DirectionType)1;
                    canMove = true;
                    return;
                }

                // Wybieranie nowego kierunku na podstawie ścian w sąsiedztwie:
                if (firstSet ||
                    !(!reservedPlace[posX, posZ + 1] && !reservedPlace[posX, posZ - 1] && reservedPlace[posX - 1, posZ] && reservedPlace[posX + 1, posZ]) &&
                    !(reservedPlace[posX, posZ + 1] && reservedPlace[posX, posZ - 1] && !reservedPlace[posX - 1, posZ] && !reservedPlace[posX + 1, posZ])
                    )
                {
                    firstSet = false;
                    while (true)
                    {
                        if (counter++ >= 4) //Sprawdzono wszysdtkie 4 kierunki
                        {
                            canMove = false;    
                            return;
                        }
                        switch (newDirection++)
                        {
                            case 0:
                                if (!reservedPlace[posX, posZ + 1])
                                {
                                    this.Direction = (DirectionType)0;
                                    canMove = true;
                                    return;
                                }
                                break;
                            case 1:
                                if (!reservedPlace[posX + 1, posZ])
                                {
                                    this.Direction = (DirectionType)1;
                                    canMove = true;
                                    return;
                                }
                                break;
                            case 2:
                                if (!reservedPlace[posX, posZ - 1])
                                {
                                    this.Direction = (DirectionType)2;
                                    canMove = true;
                                    return;
                                }
                                break;
                            default: //3
                                if (!reservedPlace[posX - 1, posZ])
                                {
                                    this.Direction = (DirectionType)3;
                                    canMove = true;
                                    return;
                                }
                                else
                                {
                                    newDirection = 0;
                                }
                                break;
                        }
                    }
                }
            }
        }
    }
}
